package uppacket

import (
	"gitee.com/yanwc/ebike-xiaoan-device/device"
	"gitee.com/yanwc/ebike-xiaoan-device/device/config"
	"gitee.com/yanwc/ebike-xiaoan-device/internal/field"
	"gitee.com/yanwc/ebike-xiaoan-device/internal/frame"
	"gitee.com/yanwc/net/utils"
	"github.com/panjf2000/gnet"
)

type StatusNotifyPacket struct{}

var _ IUpPacket = (*StatusNotifyPacket)(nil)

func (notify *StatusNotifyPacket) Do(frame frame.IFrame, c gnet.Conn) ([]byte, gnet.Action, error) {
	device, ok := device.SessionDevices.GetWithConn(c)
	if !ok {
		return nil, gnet.Close, nil
	}

	status, err := notify.ConvertToStatus(frame.Content())
	if err != nil {
		return nil, gnet.None, err
	}

	go device.OnStatusNotify(config.Context{}, status)
	return frame.WrapPacket(nil), gnet.None, nil
}

func (notify *StatusNotifyPacket) ConvertToStatus(data []byte) (field.Status, error) {
	var swBit32Raw field.SWBit32Raw
	var gsm field.GSMRaw
	var voltageMV field.VoltageMVRaw
	var timestamp field.LocationTimestampRaw
	var longitude field.LongitudeRaw
	var latitude field.LatitudeRaw
	var altitude field.AltitudeRaw
	var speed field.SpeedRaw
	var course field.CourseRaw
	var hdop field.HdopRaw
	var satellite field.SatelliteRaw
	var totalMiles field.TotalMilesRaw
	var fenceVersion field.FenceVersionRaw
	var tlvRaw field.TLVSRaw

	utils.LoadPacket(data,
		swBit32Raw[:],
		gsm[:],
		voltageMV[:],
		timestamp[:],
		longitude[:],
		latitude[:],
		altitude[:],
		speed[:],
		course[:],
		hdop[:],
		satellite[:],
		totalMiles[:],
		fenceVersion[:],
		tlvRaw)
	tlvs := tlvRaw.TLVS()
	swBit32 := swBit32Raw.Type()
	g, err := gsm.Type()
	if err != nil {
		return field.Status{}, err
	}

	return field.Status{
		SW:                field.SWBit32(swBit32),
		GSM:               g,
		VolMV:             voltageMV.Type(),
		LocationTimestamp: timestamp.Type(),
		LngGSW84:          longitude.Type(),
		LatGSW84:          latitude.Type(),
		Altitude:          altitude.Type(),
		Speed:             speed.Type(),
		Course:            course.Type(),
		Hdop:              hdop.Type(),
		Satellite:         satellite.Type(),
		TotalMiles:        totalMiles.Type(),
		FenceVersion:      fenceVersion.Type(),
		TLVS:              *tlvs,
	}, nil
}
